package dai.samples.shiro.config;

import dai.samples.shiro.filter.IsLoginFilter;
import dai.samples.shiro.filter.IsRememberFilter;
import dai.samples.shiro.shiro.CustomRealm;
import org.apache.shiro.mgt.RememberMeManager;
import org.apache.shiro.mgt.SessionsSecurityManager;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.filter.authc.AnonymousFilter;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.Cookie;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.Filter;
import java.util.HashMap;
import java.util.Map;

@Configuration
public class ShiroConfig {

    /**
     * 配置自定义Realm
     * 认证主题
     * @return
     */
    @Bean
    public CustomRealm userRealm() {
        CustomRealm userRealm = new CustomRealm();
        userRealm.setAuthenticationCacheName(Constants.USER_REALM);
        return userRealm;
    }

    /**
     * 初始化安全管理器，此配置管理shiro的所有内容
     * @return
     */
    @Bean
    public SessionsSecurityManager securityManager(@Autowired MyCacheManager cacheManager,
                                                   @Autowired DefaultWebSessionManager sessionManager) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(userRealm());
        // 此内容管理shiro的session管理
        securityManager.setSessionManager(sessionManager);
        // 此内容管理shiro的缓存管理
        // securityManager.setCacheManager(null);
        // securityManager.setCacheManager(cacheManager);
        // 此内容管理shiro的记住我管理
        securityManager.setRememberMeManager(getRememberMeManager());
        return securityManager;
    }

    /**
     * remember me 管理器
     * @return
     */
    public RememberMeManager getRememberMeManager() {
        CookieRememberMeManager rememberMeManager = new CookieRememberMeManager();
        rememberMeManager.setCookie(rememberCookie());
        // 允许的byte数组长度为16, 24,和32
        byte[] decode = new byte[]{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
        // my-shiro
        rememberMeManager.setCipherKey(decode);
        return rememberMeManager;
    }

    /**
     * rememberCookie的内容
     * @return
     */
    public Cookie rememberCookie() {
        SimpleCookie cookie = new SimpleCookie();
        cookie.setHttpOnly(true);
        cookie.setMaxAge(2592000);
        cookie.setName("rememberMe");
        return cookie;
    }



    /**
     * 设置shiro过滤器，注意bean的名字 shiroFilterFactoryBean
     * @return
     */
    @Bean(name = "shiroFilterFactoryBean")
    public ShiroFilterFactoryBean shiroFilter(@Autowired SessionsSecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
        // Shiro的核心安全接口,这个属性是必须的
        shiroFilter.setSecurityManager(securityManager);
        //自定义过滤
        Map<String, Filter> filters = new HashMap<>(16);
        filters.put("anon", new AnonymousFilter());
        filters.put("isremember", new IsRememberFilter());
        filters.put("islogin", new IsLoginFilter());

        shiroFilter.setFilters(filters);
        // 配置对应路径需要经过的过滤器
        HashMap chainMap = new HashMap();
        chainMap.putAll(getAnonMap());
        chainMap.putAll(getAuthcMap());
        shiroFilter.setFilterChainDefinitionMap(chainMap);
        return shiroFilter;
    }

    /**
     * 配置匿名访问
     * @return
     */
    private Map getAnonMap() {
        HashMap chainMap = new HashMap();
        chainMap.put("/captcha", "anon");
        chainMap.put("/logout","anon");
        chainMap.put("/layuiadmin/**", "anon");
        chainMap.put("/api/**", "anon");
        chainMap.put("/h2-console/**","anon");
        chainMap.put("/login","anon");
        return chainMap;
    }

    /**
     * 配置非匿名访问
     * @return
     */
    private Map getAuthcMap() {
        HashMap chainMap = new HashMap();
        // 只需要remember就可以访问
        chainMap.put("/remember/**", "isremember");
        // 需要登录才能访问
        chainMap.put("/**", "islogin");
        return chainMap;
    }

}
